#include "lcd_init.h"
#include "stdio.h"
#include <string.h>
// #include "app.h"

typedef void (*FunType)(void);
//**********************************write function begin********************************************
void wr_cmd_4spi_8bcs(uint8_t par)
{
    LCD_DCXLow();
    LCD_CSLow();

    LCD_SCLLow();
    if (par & 0x80)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x40)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x20)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x10)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x08)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x04)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x02)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x01)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_CSHigh();
    LCD_DCXHigh();
    HAL_Delay(5);
}
void wr_dat_4spi_8bcs(uint8_t par)
{
    LCD_DCXHigh();
    LCD_CSLow();

    LCD_SCLLow();
    if (par & 0x80)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x40)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x20)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x10)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x08)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x04)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x02)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_SCLLow();
    if (par & 0x01)
        LCD_SDAHigh();
    else
        LCD_SDALow();
    LCD_SCLHigh();

    LCD_CSHigh();
    LCD_DCXHigh();
    HAL_Delay(1);
}
void wr_cmd_parall1_8(uint16_t par)
{
    LCD_DCXLow();
    LCD_CSLow();
    LCD_WRLow();
    GPIOB->ODR = par;

    LCD_WRHigh();
}
void wr_dat_parall1_8(uint16_t par)
{
    LCD_DCXHigh();
    LCD_WRLow();
    GPIOB->ODR = par;

    LCD_WRHigh();
}
void wr_cmd_parall2_8(uint16_t par)
{
    LCD_DCXLow();
    LCD_CSLow();
    LCD_WRLow();
    GPIOB->ODR = par << 1;

    LCD_WRHigh();
}
void wr_dat_parall2_8(uint16_t par)
{
    LCD_DCXHigh();
    LCD_WRLow();
    GPIOB->ODR = par << 1;

    LCD_WRHigh();
}
//**********************************read function begin********************************************

void pb_out(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // db 0-7
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
                          GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void pb_in(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // db 0-7
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
                          GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
uint8_t i801_read_byte(void)
{
    uint8_t v;

    LCD_DCXHigh();
    LCD_RDLow();
    v = GPIOB->IDR;
    LCD_RDHigh();

    return v;
}
void rd_parall1_8(uint8_t c, uint8_t *d, uint32_t l)
{
    uint8_t buf[128];

    wr_cmd_parall1_8(c);
    pb_in();
    for (int i = 0; i < l; i++)
    {
        buf[i] = i801_read_byte();
    }
    LCD_CSHigh();
    pb_out();
    memcpy(d, buf, l);
}
//**********************************write display begin********************************************
void wr_displ_parall1_8(uint8_t color)
{
    LCD_DCXHigh();
    LCD_WRLow();
    GPIOB->ODR = color;
    LCD_WRHigh();
}
void wr_displ_parall2_18(uint16_t color1, uint16_t color2)
{
    LCD_DCXHigh();
    LCD_WRLow();
    if (color1 & 0x02)
        HAL_GPIO_WritePin(DB17_GPIO_Port, DB17_Pin, GPIO_PIN_SET);
    else
        HAL_GPIO_WritePin(DB17_GPIO_Port, DB17_Pin, GPIO_PIN_RESET);
    if (color1 & 0x01)
        HAL_GPIO_WritePin(DB16_GPIO_Port, DB16_Pin, GPIO_PIN_SET);
    else
        HAL_GPIO_WritePin(DB16_GPIO_Port, DB16_Pin, GPIO_PIN_RESET);
    GPIOB->ODR = color2;
    LCD_WRHigh();
}

void HW_Reset(void)
{
    LCD_RSTHigh();
    HAL_Delay(120);
    LCD_RSTLow();
    HAL_Delay(120);
    LCD_RSTHigh();
    HAL_Delay(200);
}

void Delay(uint32_t ms)
{
    HAL_Delay(ms);
}

void Write(uint8_t dc, uint16_t par)
{
    if (dc == 0)
    {
        LCD_DCXLow();
    }
    else
    {
        LCD_DCXHigh();
    }
    LCD_CSLow();

    for (uint8_t i = 0; i < 8; i++)
    {
        LCD_SCLLow();
        if ((par & 0x80) != 0)
        {
            LCD_SDAHigh();
        }
        else
        {
            LCD_SDALow();
        }
        LCD_SCLHigh();
        par = par << 1;
    }
    LCD_CSHigh();
}

void Write_RAM(uint16_t par)
{
    LCD_DCXHigh();
    LCD_CSLow();
    for (uint8_t i = 0; i < 8; i++)
    {
        LCD_SCLLow();
        if ((par & 0x80) != 0)
        {
            LCD_SDAHigh();
        }
        else
        {
            LCD_SDALow();
        }
        LCD_SCLHigh();
        par = par << 1;
    }
}

void Write_AA(uint16_t area_b, uint16_t area_e, uint16_t offset)
{
    uint8_t datBH, datBL = 0;
    uint8_t datEH, datEL = 0;
    datBH = (area_b + offset) >> 8;
    datBL = (area_b + offset) & 0xFF;
    datEH = (area_e + offset) >> 8;
    datEL = (area_e + offset) & 0xFF;
    Write(Parameter, datBH);
    Write(Parameter, datBL);
    Write(Parameter, datEH);
    Write(Parameter, datEL);
}

void BOE0_9(void)
{
    HW_Reset();

    Delay(120); // Delay 120ms

    Write(Command, 0x11); // Sleep out

    Delay(120); // Delay 120ms

    Write(Command, 0xB1);
    Write(Parameter, 0x05);
    Write(Parameter, 0x3C);
    Write(Parameter, 0x3C);

    Write(Command, 0xB2);
    Write(Parameter, 0x05);
    Write(Parameter, 0x3C);
    Write(Parameter, 0x3C);

    Write(Command, 0xB3);
    Write(Parameter, 0x05);
    Write(Parameter, 0x3C);
    Write(Parameter, 0x3C);
    Write(Parameter, 0x05);
    Write(Parameter, 0x3C);
    Write(Parameter, 0x3C);

    Write(Command, 0xB4); // Dot inversion
    Write(Parameter, 0x03);

    Write(Command, 0xC0);
    Write(Parameter, 0xA2);
    Write(Parameter, 0x02);
    Write(Parameter, 0x84);

    Write(Command, 0xC1);
    Write(Parameter, 0xC8);

    Write(Command, 0xC2);
    Write(Parameter, 0x0D);
    Write(Parameter, 0x00);

    Write(Command, 0xC3);
    Write(Parameter, 0x8D);
    Write(Parameter, 0x2A);

    Write(Command, 0xC4);
    Write(Parameter, 0x8D);
    Write(Parameter, 0xEE);

    Write(Command, 0xC5);
    Write(Parameter, 0x16);

    Write(Command, 0xE0);
    Write(Parameter, 0x15);
    Write(Parameter, 0x0D);
    Write(Parameter, 0x04);
    Write(Parameter, 0x04);
    Write(Parameter, 0x0C);
    Write(Parameter, 0x06);
    Write(Parameter, 0x00);
    Write(Parameter, 0x05);
    Write(Parameter, 0x07);
    Write(Parameter, 0x0B);
    Write(Parameter, 0x0C);
    Write(Parameter, 0x35);
    Write(Parameter, 0x10);
    Write(Parameter, 0x13);
    Write(Parameter, 0x05);
    Write(Parameter, 0x10);

    Write(Command, 0xE1);
    Write(Parameter, 0x13);
    Write(Parameter, 0x10);
    Write(Parameter, 0x02);
    Write(Parameter, 0x07);
    Write(Parameter, 0x09);
    Write(Parameter, 0x03);
    Write(Parameter, 0x00);
    Write(Parameter, 0x06);
    Write(Parameter, 0x08);
    Write(Parameter, 0x0D);
    Write(Parameter, 0x0D);
    Write(Parameter, 0x3A);
    Write(Parameter, 0x10);
    Write(Parameter, 0x10);
    Write(Parameter, 0x06);
    Write(Parameter, 0x10);

    Write(Command, 0x35);
    Write(Parameter, 0x00);

    Write(Command, 0x3A); // 65k mode
    Write(Parameter, 0x05);

    Write(Command, 0x36);
    Write(Parameter, 0xC8);

    // Write(Command, 0x21);

    Write(Command, 0x29); // Display on

    Write(Command, 0x2C);
}

void C096LAB_Init(void)
{
    LCD_RSTHigh();
    HAL_Delay(120);
    LCD_RSTLow();
    HAL_Delay(120);
    LCD_RSTHigh();
    HAL_Delay(200);

    wr_cmd_4spi_8bcs(0x11);
    HAL_Delay(120);

    wr_cmd_4spi_8bcs(0xB1); // 50HZ
    wr_dat_4spi_8bcs(0x05); //
    wr_dat_4spi_8bcs(0x3C);
    wr_dat_4spi_8bcs(0x3C);

    wr_cmd_4spi_8bcs(0xB2);
    wr_dat_4spi_8bcs(0x05);
    wr_dat_4spi_8bcs(0x3C);
    wr_dat_4spi_8bcs(0x3C);

    wr_cmd_4spi_8bcs(0xB3);
    wr_dat_4spi_8bcs(0x05);
    wr_dat_4spi_8bcs(0x3C);
    wr_dat_4spi_8bcs(0x3C);
    wr_dat_4spi_8bcs(0x05);
    wr_dat_4spi_8bcs(0x3C);
    wr_dat_4spi_8bcs(0x3C);

    wr_cmd_4spi_8bcs(0xB4);
    wr_dat_4spi_8bcs(0x03); // 04 DOT/Column Inversion

    wr_cmd_4spi_8bcs(0xC0); //
    wr_dat_4spi_8bcs(0xA2); //
    wr_dat_4spi_8bcs(0x02);
    wr_dat_4spi_8bcs(0x04); //

    wr_cmd_4spi_8bcs(0xC1); //
    wr_dat_4spi_8bcs(0xC8);

    wr_cmd_4spi_8bcs(0xC2); //
    wr_dat_4spi_8bcs(0x0d); //
    wr_dat_4spi_8bcs(0x00); //

    wr_cmd_4spi_8bcs(0xC3); //
    wr_dat_4spi_8bcs(0x8d); //
    wr_dat_4spi_8bcs(0x2a);

    wr_cmd_4spi_8bcs(0xC4); //
    wr_dat_4spi_8bcs(0x8d); //
    wr_dat_4spi_8bcs(0xee);

    wr_cmd_4spi_8bcs(0xC5); //
    wr_dat_4spi_8bcs(0x16); //

    //    wr_cmd_4spi_8bcs(0x21); //

    wr_cmd_4spi_8bcs(0x36); // memory data access
    wr_dat_4spi_8bcs(0xC8); // MX=0,MY=0	 C0

    wr_cmd_4spi_8bcs(0xE0); //
    wr_dat_4spi_8bcs(0x15); // p1
    wr_dat_4spi_8bcs(0x0D); // p2
    wr_dat_4spi_8bcs(0x04); // p3
    wr_dat_4spi_8bcs(0x04); // p4
    wr_dat_4spi_8bcs(0x0C); // p5
    wr_dat_4spi_8bcs(0x06); // p6
    wr_dat_4spi_8bcs(0x00); // p7
    wr_dat_4spi_8bcs(0x05); // p8
    wr_dat_4spi_8bcs(0x07); // p9
    wr_dat_4spi_8bcs(0x0B); // p10
    wr_dat_4spi_8bcs(0x0C); // p11
    wr_dat_4spi_8bcs(0x35); // p12
    wr_dat_4spi_8bcs(0x10); // p13
    wr_dat_4spi_8bcs(0x13); // p14
    wr_dat_4spi_8bcs(0x05); // p15
    wr_dat_4spi_8bcs(0x10); // p15

    wr_cmd_4spi_8bcs(0xE1); //
    wr_dat_4spi_8bcs(0x13); // p1
    wr_dat_4spi_8bcs(0x10); // p2
    wr_dat_4spi_8bcs(0x02); // p3
    wr_dat_4spi_8bcs(0x07); // p4
    wr_dat_4spi_8bcs(0x09); // p5
    wr_dat_4spi_8bcs(0x03); // p6
    wr_dat_4spi_8bcs(0x00); // p7
    wr_dat_4spi_8bcs(0x06); // p8
    wr_dat_4spi_8bcs(0x08); // p9
    wr_dat_4spi_8bcs(0x0D); // p10
    wr_dat_4spi_8bcs(0x0D); // p11
    wr_dat_4spi_8bcs(0x3A); // p12
    wr_dat_4spi_8bcs(0x10); // p13
    wr_dat_4spi_8bcs(0x10); // p14
    wr_dat_4spi_8bcs(0x06); // p15
    wr_dat_4spi_8bcs(0x10); // p15

    wr_cmd_4spi_8bcs(0x3A); // Set Color Format/interface pixel format
    wr_dat_4spi_8bcs(0x05); // 55  16 bit/pixel ,66 18 bit/pixel

    wr_cmd_4spi_8bcs(0x2A); // Set Column Address
    wr_dat_4spi_8bcs(0x00);
    wr_dat_4spi_8bcs(0x00);
    wr_dat_4spi_8bcs(0x03);
    wr_dat_4spi_8bcs(0xC0);

    wr_cmd_4spi_8bcs(0x2B);
    wr_dat_4spi_8bcs(0x01);
    wr_dat_4spi_8bcs(0x20);
    wr_dat_4spi_8bcs(0x03);
    wr_dat_4spi_8bcs(0xa0);

    wr_cmd_4spi_8bcs(0x29);
}
